package itdep.common.services.impl;

import itdep.common.domain.Entity;
import itdep.common.domain.EntityDao;
import itdep.common.domain.EntityFilter;
import itdep.common.domain.EntityFilterImpl;
import itdep.common.resolver.Resolvable;
import itdep.common.services.EntityService;
import itdep.common.services.Pagination;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.security.access.annotation.Secured;

import java.io.Serializable;
import java.util.List;

/**
 * @author Ivan Khalopik
 * @version $Revision: 4 $ $Date: 2010-06-10 13:13:16 +0000 (Thu, 10 Jun 2010) $
 */
public class EntityServiceImpl<PK extends Serializable, E extends Entity<PK>, F extends EntityFilter<PK>, D extends EntityDao<PK, E>>
		implements EntityService<PK, E, F>, ApplicationEventPublisherAware, ApplicationEventPublisher, Resolvable<Class<E>> {

	private final Class<E> entityClass;
	private final D dao;
	private ApplicationEventPublisher eventPublisher;

	@SuppressWarnings({"unchecked"})
	public EntityServiceImpl(final D dao) {
		this.dao = dao;
		this.entityClass = (dao instanceof Resolvable) ? ((Resolvable<Class<E>>) dao).getResolveKey() : null;
	}

	public Class<E> getResolveKey() {
		return entityClass;
	}

	@Secured(value = "AFTER_ACL_READ")
	public E get(final PK pk) {
		return dao().get(pk);
	}

	public int getEntitiesCount() {
		return getEntitiesCount(createDefaultFilter());
	}

	public int getEntitiesCount(final F filter) {
		return dao().count(filter);
	}

	@Deprecated
	@Secured(value = "AFTER_ACL_COLLECTION_READ")
	public List<E> getEntities(final Pagination pagination) {
		return getEntities(null, pagination);
	}

	@Secured(value = "AFTER_ACL_COLLECTION_READ")
	public List<E> getEntities(final F filter, final Pagination pagination) {
		return dao().find((filter == null)
				? createDefaultFilter()
				: filter, pagination.getStart(), pagination.getCount(), pagination.getSortDefinitions());
	}

	@Secured(value = "AFTER_ACL_READ")
	public E getUnique(final F filter) {
		return dao().findUnique(filter);
	}

	@SuppressWarnings({"unchecked"})
	public F createDefaultFilter() {
		return (F) new EntityFilterImpl();
	}

	protected D dao() {
		return dao;
	}

	public void setApplicationEventPublisher(final ApplicationEventPublisher applicationEventPublisher) {
		eventPublisher = applicationEventPublisher;
	}

	public void publishEvent(final ApplicationEvent event) {
		eventPublisher.publishEvent(event);
	}
}
